﻿// MIT License
// 开源地址：https://gitee.com/co1024/AbcMvc
// Copyright (c) 2021-2023 1024
// Abc.Mvc=Furion+EF+SqlSugar+Pear layui admin.

using SkiaSharp;

namespace Abc.Utils;

/// <summary>
/// SkiaSharp 扩展
/// </summary>
public class SkiaSharpHelper
{
    /// <summary>
    /// SkiaSharp压缩图片
    /// </summary>
    /// <example>
    /// string source = "D:\\Images\\source.png";
    /// //实验1 不改变尺寸，图片质量改为80，存为jpg图片
    /// ImageTools.Compress(source, "D:\\Images\\target-1.jpg", 1920, 80);
    /// //实验2 不改变尺寸，图片质量改为80，存为png图片
    /// ImageTools.Compress(source, "D:\\Images\\target-2.png", 1920, 80);
    /// //实验3 尺寸缩放到宽度800，图片质量改为80，存为jpg图片
    /// ImageTools.Compress(source, "D:\\Images\\target-3.jpg", 800, 80);
    /// //实验4 尺寸缩放到宽度800，图片质量改为60，存为jpg图片
    /// ImageTools.Compress(source, "D:\\Images\\target-4.jpg", 800, 60);
    /// </example>
    /// <param name="filePath">原文件位置</param>
    /// <param name="newFilePath">生成目标文件位置</param>
    /// <param name="maxWidth">最大宽度，根据此宽度计算是否需要缩放，计算新高度</param>
    /// <param name="quality">图片质量，范围0-100</param>
    public static bool Compress(string filePath, string newFilePath, decimal maxWidth = 0, int quality = 100)
    {
        try
        {
            using (var file = File.OpenRead(filePath))
            using (var fileStream = new SKManagedStream(file))
            using (var bitmap = SKBitmap.Decode(fileStream))
            {
                var width = (decimal)bitmap.Width;
                var height = (decimal)bitmap.Height;
                var newWidth = width;
                var newHeight = height;
                //maxWidth 要大于0才进行缩放，否则不做处理
                if (maxWidth > 0 && width > maxWidth)
                {
                    newWidth = maxWidth;
                    newHeight = height / width * maxWidth;
                }
                using (var resized = bitmap.Resize(new SKImageInfo((int)newWidth, (int)newHeight), SKFilterQuality.Medium))
                {
                    if (resized != null)
                    {
                        using (var image = SKImage.FromBitmap(resized))
                        using (var writeStream = File.OpenWrite(newFilePath))
                        {
                            image.Encode(SKEncodedImageFormat.Jpeg, quality).SaveTo(writeStream);

                            return true;
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
            return false;
        }
        return false;
    }

    /// <summary>
    /// 压缩并裁切图片去除上下水印
    /// </summary>
    /// <param name="filePath">原文件位置</param>
    /// <param name="newFilePath">生成目标文件位置</param>
    /// <param name="maxWidth">最大宽度，根据此宽度计算是否需要缩放，计算新高度</param>
    /// <param name="top">顶部裁切高度，单位px</param>
    /// <param name="bottom">底部裁切高度，单位px</param>
    /// <param name="quality">图片质量，范围0-100</param>
    public static void CompressAndCut(string filePath, string newFilePath, decimal maxWidth = 0, int top = 0, int bottom = 0, int quality = 100)
    {
        using (var file = File.OpenRead(filePath))
        using (var fileStream = new SKManagedStream(file))
        using (var bitmap = SKBitmap.Decode(fileStream))
        {
            var width = (decimal)bitmap.Width;
            var height = (decimal)bitmap.Height;
            var newWidth = width;
            var newHeight = height;
            //maxWidth 要大于0才进行缩放，否则不做处理
            if (maxWidth > 0 && width > maxWidth)
            {
                newWidth = maxWidth;
                newHeight = height / width * maxWidth;
            }
            using (var resized = bitmap.Resize(new SKImageInfo((int)newWidth, (int)newHeight), SKFilterQuality.Medium))
            {
                if (resized != null)
                {
                    using (var surface = SKSurface.Create(new SKImageInfo((int)newWidth, (int)newHeight - top - bottom)))
                    {
                        var canvas = surface.Canvas;
                        canvas.DrawBitmap(resized, 0, 0 - top);
                        using (var image = surface.Snapshot())
                        {
                            using (var writeStream = File.OpenWrite(newFilePath))
                            {
                                image.Encode(SKEncodedImageFormat.Jpeg, quality).SaveTo(writeStream);
                            }
                        }
                    }
                }
            }
        }
    }


    /// <summary>
    /// SkiaSharp验证文件是否是图片
    /// </summary>
    /// <param name="filePath">文件完整路径</param>
    /// <returns></returns>
    public static bool IsImage(string filePath)
    {
        //验证是否图片
        try
        {
            //using var file = File.OpenRead(filePath);
            //using var fileStream = new SKManagedStream(file);
            using var bitmap = SKBitmap.Decode(filePath);
            //bitmap 不为空标识加载图片成功，是真图片
            return bitmap != null;
        }
        catch (Exception e)
        {
            return false;
        }
    }

    /// <summary>
    /// SkiaSharp验证文件是否是图片
    /// </summary>
    /// <param name="file">上传的文件对象</param>
    /// <returns></returns>
    public static bool IsImage(IFormFile file)
    {
        //验证是否图片
        try
        {
            var dir = AppEx.GetUploadDefaultFloder() + "\\" + $"upload\\temp";
            var filePath = $"{dir}\\{DateTimeOffset.Now:yyyyMMddHHmmssfffff}{RandomHelper.GetInt(10000, 99999)}{file.FileName.GetExtension()}";
            FileHelper.CreateDirectory(dir);

            using (FileStream fs = System.IO.File.Create(filePath))
            {
                file.CopyTo(fs);
                fs.Flush();
            }

            //进行压缩
            var newFilePath = filePath.Replace(file.FileName.GetExtension(), "") + $"_test{file.FileName.GetExtension()}";
            var isCompress = Compress(filePath, newFilePath, 10, 10);

            //压缩成功了，说明是图片

            //删除临时文件
            FileHelper.TryDeleteFile(filePath);
            FileHelper.TryDeleteFile(newFilePath);

            //bitmap 不为空标识加载图片成功，是真图片
            return isCompress;
        }
        catch (Exception e)
        {
            return false;
        }
    }

}
